import React, { useEffect, CSSProperties, useRef, useState, ReactNode, ReactElement } from 'react';
import { BellOutlined } from '@ant-design/icons';
import { Tabs,  ConfigProvider, Card, Skeleton, Divider } from 'antd';
import { ColumnsType, TablePaginationConfig, TableProps, ColumnType } from 'antd/es/table';
import { FormItemProps, FormProps, FormInstance } from 'antd/es/form';
import useFetchData, { UseFetchDataAction, RequestData } from './useFetchData';
import { ActionType, ProColumns } from '@ant-design/pro-table';
import { stringify } from 'use-json-comparison';
import InfiniteScroll from 'react-infinite-scroll-component';


import List from './list';

// import { SearchConfig, TableFormItem } from './form';

import styles from './index.less';

const { TabPane } = Tabs;

export interface ColumnsState {
    show?: boolean;
    fixed?: 'right' | 'left' | undefined;
}
export type ProTableTypes = 'form' | 'list' | 'table' | 'cardList' | undefined;
export interface ProColumnType<T = unknown>
  extends Omit<ColumnType<T>, 'render' | 'children' | 'title' | 'filters'>,
    Partial<Omit<FormItemProps, 'children'>> {
  index?: number;
  title?: ReactNode | ((config: ProColumnType<T>, type: ProTableTypes) => ReactNode);
  /**
   * 自定义 render
   */
  render?: (
    text: React.ReactNode,
    record: T,
    index: number,
    action: UseFetchDataAction<RequestData<T>>,
  ) => React.ReactNode | React.ReactNode[];

  /**
   * 自定义 render，但是需要返回 string
   */
  renderText?: (
    text: any,
    record: T,
    index: number,
    action: UseFetchDataAction<RequestData<T>>,
  ) => any;

  /**
   * 自定义搜索 form 的输入
   */
  renderFormItem?: (
    item: ProColumns<T>,
    config: {
      value?: any;
      onChange?: (value: any) => void;
      onSelect?: (value: any) => void;
      type: ProTableTypes;
      defaultRender: (newItem: ProColumns<any>) => JSX.Element | null;
    },
    form: FormInstance,
  ) => JSX.Element | false | null;

  /**
   * 搜索表单的 props
   */
  formItemProps?: { [prop: string]: any };

  /**
   * 搜索表单的默认值
   */
  initialValue?: any;

  /**
   * 是否缩略
   */
  ellipsis?: boolean;
  /**
   * 是否拷贝
   */
  copyable?: boolean;

  /**
   * 值的类型
   */
  valueType?: ProColumnsValueType | ProColumnsValueTypeFunction<T>;

  /**
   * 值的枚举，如果存在枚举，Search 中会生成 select
   */
  valueEnum?: ValueEnumMap | ValueEnumObj;

  /**
   * 在查询表单中隐藏
   */
  hideInSearch?: boolean;

  /**
   * 在 table 中隐藏
   */
  hideInTable?: boolean;

  /**
   * 在新建表单中删除
   */
  hideInForm?: boolean;

  /**
   * 表头的筛选菜单项
   */
  filters?: boolean | ColumnFilterItem[];

  /**
   * form 的排序
   */
  order?: number;
}

export interface ProColumnGroupType<RecordType> extends ProColumnType<RecordType> {
    children: ProColumns<RecordType>;
}

export interface ProTableProps<T, U extends { [key: string]: any }>
  extends Omit<TableProps<T>, 'columns' | 'rowSelection'> {
    columns?: ProColumns<T>[];
    toolbar?: any;
    params?: U;

    columnsStateMap?: {
        [key: string]: ColumnsState;
  };

  onColumnsStateChange?: (map: { [key: string]: ColumnsState }) => void;

//   onSizeChange?: (size: DensitySize) => void;

  /**
   * 渲染 table
   */

  tableRender?: (
    props: ProTableProps<T, U>,
    defaultDom: JSX.Element,
    /**
     * 各个区域的 dom
     */
    domList: {
      toolbar: JSX.Element | undefined;
      alert: JSX.Element | undefined;
      table: JSX.Element | undefined;
    },
  ) => React.ReactNode;

  tableExtraRender?: (props: ProTableProps<T, U>, dataSource: T[]) => React.ReactNode;

  /**
   * 一个获得 dataSource 的方法
   */
  request?: (
    params: U & {
      pageSize?: number;
      current?: number;
    },
    sort: {
      [key: string]: 'ascend' | 'descend';
    },
    filter: { [key: string]: React.ReactText[] },
  ) => Promise<RequestData<T>>;

  /**
   * 对数据进行一些处理
   */
  postData?: (data: any[]) => any[];
  /**
   * 默认的数据
   */
  defaultData?: T[];

  /**
   * 初始化的参数，可以操作 table
   */
  actionRef?: React.MutableRefObject<ActionType | undefined> | ((actionRef: ActionType) => void);

  /**
   * 操作自带的 form
   */
  formRef?: TableFormItem<T>['formRef'];
  /**
   * 渲染操作栏
   */
//   toolBarRender?: ToolBarProps<T>['toolBarRender'] | false;

  /**
   * 数据加载完成后触发
   */
  onLoad?: (dataSource: T[]) => void;

  /**
   * 数据加载失败时触发
   */
  onRequestError?: (e: Error) => void;

  /**
   * 给封装的 table 的 className
   */
  tableClassName?: string;

  /**
   * 给封装的 table 的 style
   */
  tableStyle?: CSSProperties;

  /**
   * 左上角的 title
   */
  headerTitle?: React.ReactNode;

  /**
   * 默认的操作栏配置
   */
//   options?: OptionConfig<T> | false;
  /**
   * 是否显示搜索表单
   */
  search?: boolean | SearchConfig 

  /**
   * type="form" 和 搜索表单 的 Form 配置
   * 基本配置与 antd Form 相同
   *  但是劫持了 form 的配置
   */
  form?: Omit<FormProps, 'form'>;
  /**
   * 如何格式化日期
   * 暂时只支持 moment
   * string 会格式化为 YYYY-DD-MM
   * number 代表时间戳
   */
  dateFormatter?: 'string' | 'number' | false;
  /**
   * 格式化搜索表单提交数据
   */
  beforeSearchSubmit?: (params: Partial<T>) => Partial<T>;
  /**
   * 自定义 table 的 alert
   * 设置或者返回false 即可关闭
   */
  tableAlertRender?:
    | ((props: {
        intl: IntlType;
        selectedRowKeys: (string | number)[];
        selectedRows: T[];
      }) => React.ReactNode)
    | false;
  /**
   * 自定义 table 的 alert 的操作
   * 设置或者返回false 即可关闭
   */
  tableAlertOptionRender?:
    | ((props: { intl: IntlType; onCleanSelected: () => void }) => React.ReactNode)
    | false;

  rowSelection?: TableProps<T>['rowSelection'] | false;

  style?: React.CSSProperties;

  /**
   * 支持 ProTable 的类型
   */
//   type?: ProTableTypes;

  /**
   * 提交表单时触发
   */
  onSubmit?: (params: U) => void;

  /**
   * 重置表单时触发
   */
  onReset?: () => void;

  type?: string;

  /**
   * 空值时显示
   */
//   columnEmptyText?: ColumnEmptyText;
}


const MobileTable = <T extends {}, U extends object>(
    props: ProTableProps<T, U> & {
      defaultClassName?: string;
    },
) => {
  const {
    request,
    className: propsClassName,
    params = {},
    defaultData = [],
    headerTitle,
    postData,
    pagination,
    actionRef,
    columns: propsColumns = [],
    toolBarRender,
    onLoad,
    onRequestError,
    style,
    tableStyle,
    tableClassName,
    columnsStateMap,
    onColumnsStateChange,
    options,
    search = true,
    rowSelection: propsRowSelection = false,
    beforeSearchSubmit = (searchParams: Partial<U>) => searchParams,
    tableAlertRender,
    defaultClassName,
    formRef,
    type = '',
    onReset = () => {},
    columnEmptyText = '-',
    toolbar,
    onChange,
    ...rest
  } = props;

  const [loading, setLoading] = useState(false);
  const [formSearch, setFormSearch] = useState<{}>(() => rest.form?.initialValues);
  const [dataSource, setDataSource] = useState<T[]>([]);
  const [proFilter, setProFilter] = useState<{
    [key: string]: React.ReactText[];
  }>({});
  const [proSort, setProSort] = useState<{
    [key: string]: 'ascend' | 'descend';
  }>({});
  // const rootRef = useRef<HTMLDivElement>(null);

  /**
   * 需要初始化 不然默认可能报错
   * 这里取了 defaultCurrent 和 current
   * 为了保证不会重复刷新
   */
   const fetchPagination =
   typeof propsPagination === 'object'
     ? (propsPagination as TablePaginationConfig)
     : { defaultCurrent: 1, defaultPageSize: 20, pageSize: 20, current: 1 };
  const action = useFetchData(
    async ({ pageSize, current }) => {
      if (!request) {
        return {
          data: props.dataSource || [],
          success: true,
        } as RequestData<T>;
      }
      const msg = await request(
        {
          current,
          pageSize,
          ...formSearch,
          ...params,
        } as U,
        proSort,
        proFilter,
      );
      if (postData) {
        return { ...msg, data: postData(msg.data) };
      }
      return msg;
    },
    defaultData,
    {
      defaultCurrent: fetchPagination.current || fetchPagination.defaultCurrent,
      defaultPageSize: fetchPagination.pageSize || fetchPagination.defaultPageSize,
      onLoad,
      onRequestError,
      effects: [stringify(params), stringify(formSearch), stringify(proFilter), stringify(proSort)],
    },
  );

  const renderTabBar = () => {
    return (<Tabs
      className={styles.mobileTabs} 
      defaultActiveKey={toolbar.menu? toolbar.menu.activeKey: ''} 
      onChange={(key: string) => toolbar.menu && toolbar.menu.onChange(key)}>
      {toolbar.menu
        &&toolbar.menu.items 
        && toolbar.menu.items.length > 0 
        && toolbar.menu.items.map((item: any) => 
          <TabPane tab={item.label} key={item.key} />)}
    </Tabs>)
  }

  const loadMoreData = () => {
    if (loading) {
      return;
    }
    setLoading(true);
    onChange({
      current: ++pagination.current,
      pageSize: pagination.pageSize
    })
  }

  useEffect(() => {
    // 数据源更新时 取消所有选中项
    // onCleanSelected();
    let requestData: any = request ? (action.dataSource as T[]) : props.dataSource || [];
    setDataSource(loading? [...dataSource, ...requestData]: requestData);
    setLoading(false);
    
  }, [props.dataSource, action.dataSource]);


  return (
    <ConfigProvider>
      <div id="ant-design-pro-table" >
        {type !== 'form' && props.tableExtraRender && (
          <div >{props.tableExtraRender(props, dataSource)}</div>
        )}
        {toolbar && renderTabBar()}
        {type !== 'form' && (
          <Card
            bordered={false}
            style={{
              height: '100%',
              background: 'none'
            }}
            bodyStyle={{
              padding: 0,
            }}
          >
            {pagination && pagination.total
              ?(<InfiniteScroll
                    dataLength={dataSource.length}
                    next={loadMoreData}
                    hasMore={dataSource.length < pagination.total}
                    loader={<Divider plain>Loading……</Divider>}
                    endMessage={<Divider plain>已经到低了……</Divider>}
                  >
                    <List
                      {...props}
                      dataSource={dataSource}
                    />
                </InfiniteScroll>)
              :(<List
                  {...props}
                  dataSource={dataSource}
                />)
            }
            
          </Card>
          
        )}
      </div>
    </ConfigProvider>
  );
};


export default MobileTable;